import base64
import json
import os
import time
import uuid
from urllib.parse import urljoin
from config.settings import UPLOAD_FOLDER

from flask import Blueprint, request, jsonify, url_for, render_template, send_from_directory

from utils import compress_images

ue_bp = Blueprint('ueditor', __name__)
# 创造一个上传文件的路径
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

ueditor_dir = os.path.join(os.path.dirname(__file__), "..", "static/ueditor")

# 读取官方 config.json（务必保持原样）
with open(os.path.join(ueditor_dir, 'config.json'), 'r', encoding='utf-8') as f:
    UEDITOR_CONFIG = json.load(f)


# ------------- 路由 1：UEditor 统一入口 ------------
# 为ueditor的文件上传功能写一个接口
# 在UE.getEditor需要配置serverUrl值等于"/ueditor",
@ue_bp.route('/ueditor', methods=['GET', 'POST'])
def ueditor_upload():
    action = request.args.get('action')
    if action == 'config':
        # 返回 Ueditor 配置 JSON，可以直接写成return jsonify({配置项目})，也可以写到config.json中，然后返回给ue,如下
        # return jsonify({ # 图片上传配置
        #     "imageActionName": "image",
        #     # 提交的图片表单名称，默认值：upfile
        #     "imageFieldName": "file",})
        # 读取配置文件内容并返回JSON响应
        with open(os.path.join(ueditor_dir, 'config.json'), 'r', encoding='utf-8') as f:
            config_data = json.load(f)
        return jsonify(config_data)
    # 2. 上传图片
    elif action == 'uploadimage':
        return handle_upload('image')
    # 3. 上传涂鸦
    elif action == 'uploadscrawl':
        return handle_scrawl()
    # 4. 上传附件/视频
    elif action == 'uploadfile':
        return handle_upload('file')
    elif action == 'uploadvideo':
        return handle_upload('video')

    # 5. 在线管理
    elif action in ('listimage', 'listfile'):
        return handle_list(action)

    # 6. 远程抓图
    elif action == 'catchimage':
        return handle_catch()

    return jsonify({"state": "未知操作"})


# ------------- 路由 2：静态访问上传文件 -------------
@ue_bp.route('/upload/<path:filename>')
def uploaded_file(filename):
    return send_from_directory(UPLOAD_FOLDER, filename)


# ------------- 工具函数 -------------
# 检查给定文件名是否以指定的任一扩展名结尾 / any(...)：只要有一个扩展名匹配成功，就返回 True。
def allowed_file(filename, allow_exts):
    return any(filename.lower().endswith(e) for e in allow_exts)


# 没用到
def build_url(path):
    '''request.host_url：Flask 中 request 对象提供的当前请求的完整域名（例如 http://127.0.0.1:5000/）。
urljoin(...)：来自标准库 urllib.parse，用于把两个 URL 拼接成一个合法的完整 URL。'''
    # 生成外链，需与 config.json 中 imageUrlPrefix 对应
    return urljoin(request.host_url, path)


def handle_upload(_type):
    """通用上传处理"""
    field_name = {
        'image': UEDITOR_CONFIG['imageFieldName'],
        'file': UEDITOR_CONFIG['fileFieldName'],
        'video': UEDITOR_CONFIG['videoFieldName']
    }[_type]  # 根据传入的_type键,来获取字典中对应的值

    if field_name not in request.files:
        '''request.files 是 Flask 提供的一个字典，包含了所有通过表单上传的文件。这句话是在判断：前端有没有上传名为 field_name'''
        return jsonify({'state': 'ERROR: no file'})

    f = request.files[field_name]
    if f.filename == '':
        return jsonify({'state': 'ERROR: empty file'})

    allow_exts = {
        'image': UEDITOR_CONFIG['imageAllowFiles'],
        'file': UEDITOR_CONFIG['fileAllowFiles'],
        'video': UEDITOR_CONFIG['videoAllowFiles']
    }[_type]

    if not allowed_file(f.filename, allow_exts):
        return jsonify({'state': 'ERROR: not allowed file type'})

    # 文件名
    ext = os.path.splitext(f.filename)[1]  # 用于将文件名分割成文件主干和扩展名两部分，这里获得扩展名
    filename = f"{uuid.uuid4().hex}{ext}"  # 重新定义文件名字，32位16进制字符串
    subdir = time.strftime("%Y%m%d")
    target_dir = os.path.join(UPLOAD_FOLDER, _type, subdir)
    os.makedirs(target_dir, exist_ok=True)
    filepath = os.path.join(target_dir, filename)
    # 保存
    f.save(filepath)
    # 是图片的话可以进行适当的压缩
    if _type == 'image':
        compress_images.compress_image(filepath, filepath, 1200)

    # 返回官方格式
    return jsonify({
        "state": "SUCCESS",
        "url": f"/upload/{_type}/{subdir}/{filename}",
        "title": filename,
        "original": f.filename
    })


def handle_scrawl():
    field = UEDITOR_CONFIG['scrawlFieldName']  # 默认是 'upfile'
    img = request.form.get(field, '')

    if not img:
        return jsonify({'state': 'ERROR: no scrawl data'})

    # 兼容   或  xxxxx
    if ',' in img:
        b64_data = img.split(',', 1)[1]
    else:
        b64_data = img

    try:
        data = base64.b64decode(b64_data)
    except Exception:
        return jsonify({'state': 'ERROR: invalid base64'})

    filename = f"{uuid.uuid4().hex}.png"
    subdir = time.strftime("%Y%m%d")
    target_dir = os.path.join(UPLOAD_FOLDER, 'scrawl', subdir)
    os.makedirs(target_dir, exist_ok=True)
    filepath = os.path.join(target_dir, filename)

    with open(filepath, 'wb') as f:
        f.write(data)

    return jsonify({
        "state": "SUCCESS",
        "url": f"/upload/scrawl/{subdir}/{filename}",
        "title": filename,
        "original": filename
    })


def handle_list(action):
    """在线图片/文件列表"""
    list_size = int(request.args.get('size', 20))
    list_size = min(list_size, 100)
    start = int(request.args.get('start', 0))

    _type = 'image' if action == 'listimage' else 'file'
    base_dir = os.path.join(UPLOAD_FOLDER, _type)
    files = []
    for root, _, filenames in os.walk(base_dir):
        for name in filenames:
            if name.startswith('.'):
                continue
            files.append(os.path.join(root, name))

    files.sort(key=lambda x: os.path.getmtime(x), reverse=True)
    total = len(files)
    files = files[start: start + list_size]

    list_result = []
    for f in files:
        url = f.replace(os.path.dirname(UPLOAD_FOLDER), '').replace('\\', '/')
        list_result.append({'url': url})

    return jsonify({
        "state": "SUCCESS",
        "list": list_result,
        "start": start,
        "total": total
    })


def handle_catch():
    """远程抓图"""
    source = request.form.getlist('source[]')
    if not source:
        return jsonify({'state': 'ERROR: no url'})

    list_result = []
    for url in source:
        try:
            import requests
            r = requests.get(url, timeout=5)
            ext = os.path.splitext(url)[1] or '.jpg'
            filename = f"{uuid.uuid4().hex}{ext}"
            subdir = time.strftime("%Y%m%d")
            target_dir = os.path.join(UPLOAD_FOLDER, 'remote', subdir)
            os.makedirs(target_dir, exist_ok=True)
            filepath = os.path.join(target_dir, filename)

            with open(filepath, 'wb') as f:
                f.write(r.content)

            list_result.append({
                'state': 'SUCCESS',
                'source': url,
                'url': f"/upload/remote/{subdir}/{filename}"
            })
        except Exception as e:
            list_result.append({
                'state': 'ERROR',
                'source': url,
                'url': ''
            })

    return jsonify({
        'state': 'SUCCESS',
        'list': list_result
    })
